package com.free.others;

import java.util.Vector;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.Accessible;
import org.eclipse.swt.accessibility.AccessibleControlAdapter;
import org.eclipse.swt.accessibility.AccessibleControlEvent;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;

/**
 * <p>
 * Title: Eclipse Plugin Development
 * </p>
 * <p>
 * Description: Free download
 * </p>
 * <p>
 * mail: ganshm@gmail.com
 * </p>
 */

public class ColorList extends Canvas
{
    static int COLORS[] = {SWT.COLOR_RED, SWT.COLOR_GREEN, SWT.COLOR_BLUE, SWT.COLOR_MAGENTA, SWT.COLOR_YELLOW, SWT.COLOR_CYAN, SWT.COLOR_DARK_RED, SWT.COLOR_DARK_GREEN, SWT.COLOR_DARK_BLUE, SWT.COLOR_DARK_MAGENTA, SWT.COLOR_DARK_YELLOW,
        SWT.COLOR_DARK_CYAN};
    
    static String COLORSNAME[] = {"红色", "绿色", "蓝色", "紫色", "黄色", "青色", "暗红色", "暗绿色", "暗蓝色", "暗紫色", "暗黄色", "暗青色"};
    
    Vector colors = new Vector();
    
    Vector colorNames = new Vector();
    
    int rowSel = -1;
    
    int oldRowSel = -1;
    
    int cx, cy;
    
    int maxX = 200, maxY;
    
    int lineHeight = 18;
    
    Vector selectionListeners = new Vector();
    
    public ColorList(Composite parent, int style)
    {
        super(parent, style);
        init();
    }
    
    void init()
    {
        cx = 0;
        cy = 0;
        addPaintListener(new PaintListener()
        {
            public void paintControl(PaintEvent e)
            {
                GC gc = e.gc;
                Point size = getSize();
                int beginx = e.x;
                int beginy = (e.y / lineHeight) * lineHeight;
                int beginLine = (e.y - cy) / lineHeight;
                int endLine = beginLine + e.height / lineHeight + 1;
                if (endLine > getItemCount())
                    endLine = getItemCount();
                for (int i = beginLine; i < endLine; i++)
                {
                    boolean selected = false;
                    if (i == rowSel)
                        selected = true;
                    onPaint(gc, i, cx, beginy + (i - beginLine) * lineHeight, selected);
                }
                
            }
        });
        addMouseListener(new MouseListener()
        {
            public void mouseDoubleClick(MouseEvent e)
            {
                
            }
            
            public void mouseDown(MouseEvent e)
            {
                int row = (e.y - cy) / lineHeight;
                if (row >= 0)
                {
                    oldRowSel = rowSel;
                    rowSel = row;
                }
                if (oldRowSel != rowSel)
                {
                    ((Canvas)e.getSource()).redraw(cx, (e.y / lineHeight) * lineHeight, maxX, lineHeight, false);
                    ((Canvas)e.getSource()).redraw(cx, (oldRowSel + cy / lineHeight) * lineHeight, maxX, lineHeight, false);
                }
                selectionChanged();
            }
            
            public void mouseUp(MouseEvent e)
            {
                
            }
            
        });
        addListener(SWT.KeyDown, new Listener()
        {
            public void handleEvent(Event event)
            {
                switch (event.keyCode)
                {
                    case SWT.ARROW_UP: // up arrow key
                        if (rowSel != 0)
                        {
                            oldRowSel = rowSel;
                            rowSel--;
                            if (oldRowSel != rowSel)
                            {
                                ((Canvas)event.widget).redraw(cx, rowSel * lineHeight + cy, maxX, lineHeight * 2, false);
                            }
                            if (rowSel < -cy / lineHeight)
                            {
                                ScrollBar bar = ((Canvas)event.widget).getVerticalBar();
                                bar.setSelection(bar.getSelection() - lineHeight);
                                scrollVertical(bar);
                            }
                            selectionChanged();
                        }
                        break;
                    case SWT.ARROW_DOWN: // down arror key
                        if (rowSel < colors.size() - 1)
                        {
                            oldRowSel = rowSel;
                            rowSel++;
                            if (oldRowSel != rowSel)
                            {
                                ((Canvas)event.widget).redraw(cx, (rowSel + cy / lineHeight) * lineHeight, maxX, lineHeight, false);
                                ((Canvas)event.widget).redraw(cx, (oldRowSel + cy / lineHeight) * lineHeight, maxX, lineHeight, false);
                            }
                            if (rowSel >= (((Canvas)event.widget).getClientArea().height - cy) / lineHeight)
                            {
                                ScrollBar bar = ((Canvas)event.widget).getVerticalBar();
                                if (bar != null)
                                {
                                    bar.setSelection(bar.getSelection() + lineHeight);
                                    scrollVertical(bar);
                                }
                            }
                            selectionChanged();
                        }
                        break;
                }
            }
        });
        addControlListener(new ControlAdapter()
        {
            public void controlResized(ControlEvent event)
            {
                Point size = getSize();
                maxX = size.x * 3 / 2;
                maxY = colors.size() * lineHeight;
                resizeScrollBars();
            }
        });
        addFocusListener(new FocusListener()
        {
            public void focusGained(FocusEvent e)
            {
                ((Canvas)e.getSource()).redraw(cx, rowSel * lineHeight, maxX, lineHeight, true);
            }
            
            public void focusLost(FocusEvent e)
            {
                ((Canvas)e.getSource()).redraw(cx, rowSel * lineHeight, maxX, lineHeight, true);
            }
        });
        addTraverseListener(new TraverseListener()
        {
            public void keyTraversed(TraverseEvent e)
            {
                if (e.detail == SWT.TRAVERSE_TAB_NEXT || e.detail == SWT.TRAVERSE_TAB_PREVIOUS)
                {
                    e.doit = true;
                }
            };
            
        });
        ScrollBar bar = getHorizontalBar();
        if (bar != null)
        {
            bar.addSelectionListener(new SelectionAdapter()
            {
                public void widgetSelected(SelectionEvent event)
                {
                    scrollHorizontal((ScrollBar)event.widget);
                }
            });
        }
        bar = getVerticalBar();
        if (bar != null)
        {
            bar.addSelectionListener(new SelectionAdapter()
            {
                public void widgetSelected(SelectionEvent event)
                {
                    scrollVertical((ScrollBar)event.widget);
                }
            });
        }
        resizeScrollBars();
        addAccessibility();
    }
    
    private void addAccessibility()
    {
        Accessible accessible = getAccessible();
        accessible.addAccessibleControlListener(new AccessibleControlAdapter()
        {
            public void getRole(AccessibleControlEvent e)
            {
                int role = 0;
                int childID = e.childID;
                if (childID == ACC.CHILDID_SELF)
                {
                    role = ACC.ROLE_LIST;
                }
                else if (childID >= 0 && childID < colors.size())
                {
                    role = ACC.ROLE_LISTITEM;
                }
                e.detail = role;
            }
            
            public void getValue(AccessibleControlEvent e)
            {
                int childID = e.childID;
                if (childID == ACC.CHILDID_SELF)
                {
                    e.result = getText();
                }
                else if (childID >= 0 && childID < colors.size())
                {
                    e.result = (String)colorNames.get(childID);
                }
            }
            
            public void getChildAtPoint(AccessibleControlEvent e)
            {
                Point testPoint = toControl(new Point(e.x, e.y));
                int childID = ACC.CHILDID_NONE;
                childID = (testPoint.y - cy) / lineHeight;
                if (childID == ACC.CHILDID_NONE)
                {
                    Rectangle location = getBounds();
                    location.height = location.height - getClientArea().height;
                    if (location.contains(testPoint))
                    {
                        childID = ACC.CHILDID_SELF;
                    }
                }
                e.childID = childID;
                
            }
            
            public void getLocation(AccessibleControlEvent e)
            {
                Rectangle location = null;
                int childID = e.childID;
                if (childID == ACC.CHILDID_SELF)
                {
                    location = getBounds();
                }
                if (childID >= 0 && childID < colors.size())
                {
                    location = new Rectangle(cx, childID * lineHeight + cy, maxX, lineHeight);
                }
                if (location != null)
                {
                    Point pt = toDisplay(new Point(location.x, location.y));
                    e.x = pt.x;
                    e.y = pt.y;
                    e.width = location.width;
                    e.height = location.height;
                }
                
            }
            
            public void getChildCount(AccessibleControlEvent e)
            {
                e.detail = colors.size();
            }
            
            public void getState(AccessibleControlEvent e)
            {
                int state = 0;
                int childID = e.childID;
                if (childID == ACC.CHILDID_SELF)
                {
                    state = ACC.STATE_NORMAL;
                }
                else if (childID >= 0 && childID < colors.size())
                {
                    state = ACC.STATE_SELECTABLE;
                    if (isFocusControl())
                    {
                        state |= ACC.STATE_FOCUSABLE;
                    }
                    if (rowSel == childID)
                    {
                        state |= ACC.STATE_SELECTED;
                        if (isFocusControl())
                        {
                            state |= ACC.STATE_FOCUSED;
                        }
                    }
                }
                e.detail = state;
                
            }
            
        });
    }
    
    void onPaint(GC gc, int row, int beginx, int beginy, boolean isSelected)
    {
        Color initColor = gc.getBackground();
        Color initForeColor = gc.getForeground();
        if (isSelected)
        {
            gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION));
            gc.fillRectangle(beginx, beginy, maxX, lineHeight);
            gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION_TEXT));
        }
        else
        {
            gc.setBackground(initColor);
        }
        gc.drawString((String)colorNames.get(row), beginx + 40, beginy);
        Color color = Display.getCurrent().getSystemColor(((Integer)colors.get(row)).intValue());
        gc.setBackground(color);
        gc.fillRectangle(beginx + 2, beginy + 2, 30, lineHeight - 4);
        gc.setBackground(initColor);
        gc.setForeground(initForeColor);
        if (isFocusControl() && isSelected)
            gc.drawFocus(cx, beginy, maxX, lineHeight);
    }
    
    void resizeScrollBars()
    {
        Rectangle clientArea = getClientArea();
        ScrollBar hbar = getHorizontalBar();
        if (hbar != null)
        {
            hbar.setMaximum(maxX);
            hbar.setThumb(clientArea.width);
            hbar.setPageIncrement(clientArea.width);
        }
        
        ScrollBar vbar = getVerticalBar();
        if (vbar != null)
        {
            vbar.setMaximum(maxY);
            vbar.setThumb(clientArea.height);
            vbar.setPageIncrement(clientArea.height);
            vbar.setIncrement(lineHeight);
            if (clientArea.height >= lineHeight * getItemCount() + 2)
                vbar.setVisible(false);
            else
                vbar.setVisible(true);
        }
    }
    
    void scrollHorizontal(ScrollBar scrollBar)
    {
        Rectangle bounds = getClientArea();
        int x = -scrollBar.getSelection();
        if (x + maxX < bounds.width)
        {
            x = bounds.width - maxX;
        }
        scroll(x, cy, cx, cy, maxX, maxY, false);
        cx = x;
    }
    
    void scrollVertical(ScrollBar scrollBar)
    {
        Rectangle bounds = getClientArea();
        int y = -scrollBar.getSelection();
        if (y + maxY < bounds.height)
        {
            y = bounds.height - maxY;
        }
        if (y % lineHeight != 0)
            y = y - y % lineHeight - lineHeight;
        scroll(cx, y, cx, cy, maxX, maxY, false);
        cy = y;
    }
    
    public Point computeSize(int wHint, int hHint, boolean changed)
    {
        int width = 300, height = lineHeight * (getItemCount()) + 50;
        if (wHint != SWT.DEFAULT)
            width = wHint;
        if (hHint != SWT.DEFAULT)
            height = hHint;
        return new Point(width + 2, height + 2);
        
    }
    
    public void setSelection(int index)
    {
        if (index >= getItemCount() || index < 0)
            return;
        oldRowSel = rowSel;
        rowSel = index;
        selectionChanged();
    }
    
    public int getSelectionIndex()
    {
        return rowSel;
    }
    
    public int getItemHeight()
    {
        return lineHeight;
    }
    
    public void setItemHeight(int height)
    {
        lineHeight = height;
    }
    
    public int getItemCount()
    {
        return colors.size();
    }
    
    public void add(int colorIndex, String colorName)
    {
        colorNames.add(colorName);
        colors.add(new Integer(colorIndex));
    }
    
    public void setDefault()
    {
        for (int i = 0; i < COLORS.length; i++)
        {
            colors.add(new Integer(COLORS[i]));
            colorNames.add(COLORSNAME[i]);
        }
    }
    
    public void addSelectionListener(SelectionListener listener)
    {
        selectionListeners.addElement(listener);
    }
    
    public void removeImageClickedListener(SelectionListener listener)
    {
        selectionListeners.removeElement(listener);
    }
    
    public void selectionChanged()
    {
        Event event = new Event();
        event.widget = this;
        SelectionEvent e = new SelectionEvent(event);
        for (int i = 0; i < selectionListeners.size(); i++)
        {
            SelectionListener listener = (SelectionListener)selectionListeners.elementAt(i);
            listener.widgetSelected(e);
        }
        
    }
    
    public String getText()
    {
        if (rowSel >= 0)
            return (String)colorNames.get(rowSel);
        else
            return null;
    }
}
